Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Data
Imports System.Reflection
Imports System.io
Imports Sys = System.Web.UI.WebControls

Namespace WebControls

    'Public Class ObjectDataSourceEx
    '    Inherits ObjectDataSource

    '    Public Event Sorting As ObjectDataSourceStatusEventHandler

    '    Private mViewFieldInfo As FieldInfo

    '    Public Sub New()
    '        MyBase.New()
    '        Initialize()
    '    End Sub

    '    Public Sub New(ByVal typeName As String, ByVal selectMethod As String)
    '        MyBase.New(typeName, selectMethod)
    '        Initialize()
    '    End Sub

    '    Private Sub Initialize()
    '        mViewFieldInfo = GetType(ObjectDataSource).GetField("_view", BindingFlags.Instance Or BindingFlags.NonPublic)
    '        GetViewEx()
    '    End Sub

    '    Public Property ExtendSort() As Boolean
    '        Get
    '            Return ViewState("ExtendSort")
    '        End Get
    '        Set(ByVal value As Boolean)
    '            ViewState("ExtendSort") = value
    '        End Set
    '    End Property

    '    Protected Overrides Function GetView(ByVal viewName As String) As DataSourceView
    '        If ((viewName Is Nothing) OrElse ((viewName.Length <> 0) AndAlso Not String.Equals(viewName, "DefaultView", StringComparison.OrdinalIgnoreCase))) Then
    '            Throw New ArgumentException("Invalid view name: " & viewName)
    '        End If
    '        If ExtendSort Then
    '            Return Me.GetViewEx
    '        Else
    '            Return MyBase.GetView(viewName)
    '        End If
    '    End Function

    '    Private Function GetViewEx() As DataSourceView
    '        Dim view As DataSourceView = ViewInternal
    '        If view Is Nothing Then
    '            view = New ObjectDataSourceView(Me, "DefaultView", Me.Context)
    '            If MyBase.IsTrackingViewState Then
    '                DirectCast(view, IStateManager).TrackViewState()
    '            End If
    '            ViewInternal = view
    '        End If
    '        Return view
    '    End Function

    '    Private Property ViewInternal() As DataSourceView
    '        Get
    '            Return mViewFieldInfo.GetValue(Me)
    '        End Get
    '        Set(ByVal value As DataSourceView)
    '            mViewFieldInfo.SetValue(Me, value)
    '        End Set
    '    End Property

    '    Friend Sub OnDataSourceStatus(ByVal e As ObjectDataSourceStatusEventArgs)
    '        RaiseEvent Sorting(Me, e)
    '    End Sub

    'End Class

    'Friend Class ObjectDataSourceView
    '    Inherits System.Web.UI.WebControls.ObjectDataSourceView

    '    Private mOwner As ObjectDataSource

    '    Public Sub New(ByVal owner As ObjectDataSource, ByVal name As String, ByVal context As System.Web.HttpContext)
    '        MyBase.New(owner, name, context)
    '        mOwner = owner
    '    End Sub

    '    Private ReadOnly Property ExtendSort() As Boolean
    '        Get
    '            If TypeOf mOwner Is ObjectDataSource Then
    '                Return DirectCast(mOwner, ObjectDataSourceEx).ExtendSort
    '            End If
    '            Return False
    '        End Get
    '    End Property

    '    Protected Overrides Function ExecuteSelect(ByVal arguments As System.Web.UI.DataSourceSelectArguments) As System.Collections.IEnumerable
    '        If ExtendSort Then
    '            Return ExecuteSelectEx(arguments)
    '        Else
    '            Return MyBase.ExecuteSelect(arguments)
    '        End If
    '    End Function

    '    Private Function ExecuteSelectEx(ByVal arguments As DataSourceSelectArguments) As IEnumerable
    '        Dim sortExp As String = Nothing
    '        Dim sort As Boolean = False
    '        If arguments.SortExpression <> "" Then
    '            sortExp = arguments.SortExpression
    '            arguments.SortExpression = ""
    '            sort = True
    '        End If
    '        Dim list As IEnumerable = MyBase.ExecuteSelect(arguments)
    '        If sort Then
    '            Dim dict As New Dictionary(Of String, Object)
    '            dict.Add("SortExpression", sortExp)
    '            Dim e1 As New ObjectDataSourceStatusEventArgs(list, dict)
    '            Dim odsEx As ObjectDataSourceEx = mOwner
    '            odsEx.OnDataSourceStatus(e1)
    '            If dict.ContainsKey("SortResult") Then
    '                Dim sortResult As IList = dict("SortResult")
    '                If sortResult IsNot Nothing Then
    '                    list = sortResult
    '                End If
    '            End If
    '            arguments.SortExpression = sortExp
    '        End If
    '        Return list
    '    End Function

    '    'Public Overrides Sub [Select](ByVal arguments As System.Web.UI.DataSourceSelectArguments, ByVal callback As System.Web.UI.DataSourceViewSelectCallback)
    '    '    MyBase.[Select](arguments, callback)
    '    'End Sub

    '    'Protected Overrides Sub OnSelecting(ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs)
    '    '    MyBase.OnSelecting(e)
    '    'End Sub

    '    'Protected Overrides Sub OnSelected(ByVal e As System.Web.UI.WebControls.ObjectDataSourceStatusEventArgs)
    '    '    MyBase.OnSelected(e)
    '    'End Sub

    'End Class

    <ToolboxData("<{0}:GridView runat=server></{0}:GridView>")> _
    Public Class GridView
        Inherits Sys.GridView

        Private mIsManual As Boolean

        Public Overloads Property SortExpression() As String
            Get
                If Me.DataSourceID <> "" Then
                    Return MyBase.SortExpression
                End If
                Return ViewState("SortExpression")
            End Get
            Set(ByVal value As String)
                ViewState("SortExpression") = value
            End Set
        End Property

        Public Overloads Property SortDirection() As SortDirection
            Get
                If Me.DataSourceID <> "" Then
                    Return MyBase.SortExpression
                ElseIf ViewState("SortDirection") IsNot Nothing Then
                    Return ViewState("SortDirection")
                End If
                Return SortDirection.Ascending
            End Get
            Set(ByVal value As SortDirection)
                ViewState("SortDirection") = value
            End Set
        End Property

        Private Function GetSortExpression() As String
            If SortExpression = "" Then
                Return ""
            Else
                Return String.Format("[{0}] {1}", SortExpression, IIf(SortDirection = SortDirection.Ascending, "ASC", "DESC"))
            End If
        End Function

        <Category("Appearance")> _
        <Editor("System.Web.UI.Design.ImageUrlEditor", GetType(System.Drawing.Design.UITypeEditor))> _
        <Description("Setting asceding ico."), Browsable(True)> _
        Public Property AscendingImageUrl() As String
            Get
                If ViewState("SortImageAsc") IsNot Nothing Then
                    Return ViewState("SortImageAsc")
                End If
                Return ""
            End Get
            Set(ByVal value As String)
                ViewState("SortImageAsc") = value
            End Set
        End Property

        <Category("Appearance")> _
        <Editor("System.Web.UI.Design.ImageUrlEditor", GetType(System.Drawing.Design.UITypeEditor))> _
        <Description("Setting desceding ico."), Browsable(True)> _
         Public Property DescendingImageUrl() As String
            Get
                If ViewState("SortImageDesc") IsNot Nothing Then
                    Return ViewState("SortImageDesc")
                End If
                Return ""
            End Get
            Set(ByVal value As String)
                ViewState("SortImageDesc") = value
            End Set
        End Property

        Private Sub CheckEmptyDataTemplate()
            If MyBase.EmptyDataTemplate Is Nothing Then
                MyBase.EmptyDataTemplate = New EmptyDataTemplate
            End If
        End Sub

        Protected Overrides Sub OnRowCreated(ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
            If e.Row.RowType = DataControlRowType.Header Then
                For Each cell As TableCell In e.Row.Cells
                    If cell.Controls.Count > 0 AndAlso TypeOf cell.Controls(0) Is LinkButton Then
                        Dim lnkbtn As LinkButton = DirectCast(cell.Controls(0), LinkButton)
                        Dim name As String = lnkbtn.Text
                        If mIsManual Then
                            lnkbtn.OnClientClick = "javascript: return false;"
                            Continue For
                        End If
                        Dim sortExp As String = lnkbtn.CommandArgument
                        If sortExp <> "" Then
                            If SortExpression = sortExp Then
                                ShowSortImage(cell)
                                cell.ToolTip = String.Format("Click to sort by {0} in {1} order.", name, IIf(SortDirection = SortDirection.Descending, SortDirection.Ascending.ToString.ToLower, SortDirection.Descending.ToString.ToLower))
                            Else
                                cell.ToolTip = String.Format("Click to sort by {0} in ascending order.", name)
                            End If
                        End If
                    End If
                Next
            End If
            MyBase.OnRowCreated(e)
        End Sub

        Private Sub ShowSortImage(ByVal tc As TableCell)
            If Me.SortExpression = "" Then Exit Sub
            Dim imgUrl As String = IIf(SortDirection = SortDirection.Ascending, AscendingImageUrl, DescendingImageUrl)
            If imgUrl = "" Then Exit Sub
            Dim img As New System.Web.UI.WebControls.Image
            img.ImageUrl = imgUrl
            img.Style.Add("margin", "0 0 0 3")
            tc.Wrap = False
            tc.Controls.Add(img)
        End Sub

        Protected Overrides Sub OnSorting(ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs)
            If SortExpression <> e.SortExpression Then
                SortExpression = e.SortExpression
                SortDirection = SortDirection.Ascending
            Else
                SortDirection = IIf(SortDirection = SortDirection.Ascending, SortDirection.Descending, SortDirection.Ascending)
            End If

            RaiseEvent GetBindData()
        End Sub

        Protected Overrides Sub OnPageIndexChanging(ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)
            Me.PageIndex = e.NewPageIndex
            RaiseEvent GetBindData()
        End Sub

        Protected Overrides Function CreateChildControls(ByVal dataSource As System.Collections.IEnumerable, ByVal dataBinding As Boolean) As Integer
            mIsManual = False
            CheckEmptyDataTemplate()
            If IsEmptyDataSource(dataSource) Then
                mIsManual = True
                Return MyBase.CreateChildControls(New EmptyDataSource, dataBinding)
            Else
                Return MyBase.CreateChildControls(dataSource, dataBinding)
            End If
        End Function

        Public Event GetBindData()

        Public Sub OnBind(Of T)(Optional ByVal pageIndex As Integer = 0)
            If Not IsEmptyDataSource(MyBase.DataSource) AndAlso SortExpression IsNot Nothing Then
                SortDataSource(Of T)(MyBase.DataSource)
            End If

            MyBase.ShowHeader = True
            MyBase.PageIndex = pageIndex
            MyBase.DataBind()
        End Sub

        Private Function IsEmptyDataSource(ByVal dataSource As Object) As Boolean
            If dataSource Is Nothing Then
                Return True
            End If

            If TypeOf dataSource Is DataSet Then
                Return DirectCast(dataSource, DataSet).Tables(0).Rows.Count = 0
            ElseIf TypeOf dataSource Is DataTable Then
                Return DirectCast(dataSource, DataTable).Rows.Count = 0
            ElseIf TypeOf dataSource Is ICollection Then
                Return DirectCast(dataSource, ICollection).Count = 0
            ElseIf TypeOf dataSource Is EmptyDataSource Then
                Return True
            Else
                Return False
            End If

        End Function

        Private Sub SortDataSource(Of T)(ByVal dataSource As Object)
            If dataSource Is Nothing Then
                Exit Sub
            End If

            If TypeOf dataSource Is DataSet Then
                Dim dv As DataView = DirectCast(dataSource, DataSet).Tables(0).DefaultView
                dv.Sort = GetSortExpression()
                dataSource = dv
            ElseIf TypeOf dataSource Is DataTable Then
                Dim dv As DataView = DirectCast(dataSource, DataTable).DefaultView
                dv.Sort = GetSortExpression()
                dataSource = dv
            ElseIf TypeOf dataSource Is IList(Of T) Then
                Dim perwr As New PredicateWrapper()
                perwr.PropertyName = Me.SortExpression
                perwr.IsAsc = (SortDirection = SortDirection.Ascending)
                DirectCast(dataSource, List(Of T)).Sort(AddressOf perwr.Comparsion(Of T))
            End If
        End Sub

    End Class

    Public Class EmptyDataSource
        Inherits ArrayList

        Private mFakeCount As Integer = 2

        Public Sub New()
        End Sub

        Public Sub New(ByVal fakeCount As Integer)
            mFakeCount = fakeCount
        End Sub

        Public Property FakeCount() As Integer
            Get
                Return mFakeCount
            End Get
            Set(ByVal value As Integer)
                mFakeCount = value
            End Set
        End Property

        Public Overrides ReadOnly Property Count() As Integer
            Get
                Dim cc As Integer = MyBase.Count
                If mFakeCount > 0 Then
                    mFakeCount -= 1
                    If cc = 0 Then
                        cc = 1
                    End If
                End If
                Return cc
            End Get
        End Property

    End Class

    Public Class EmptyDataTemplate
        Implements ITemplate

        Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
            Dim lbl As New Label
            lbl.Text = "No record found."
            container.Controls.Add(lbl)
        End Sub

    End Class

End Namespace
